package jp.joogoo.web.model;

import java.io.Serializable;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.repackaged.org.json.JSONException;
import com.google.appengine.repackaged.org.json.JSONObject;

import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
import oauth.signpost.basic.DefaultOAuthConsumer;
import oauth.signpost.basic.DefaultOAuthProvider;

import org.slim3.datastore.Attribute;
import org.slim3.datastore.Model;

@Model(schemaVersion = 1)
public class M_service implements Serializable {

    private static final long serialVersionUID = 1L;

    @Attribute(primaryKey = true)
    private Key key;    // サービスID
    @Attribute(version = true)  
    private Long version;   // バージョンNo(多重更新検知用)

    private String serviceName; // サービス名称
    private String serviceProvider;
    private String consumerToken;

    /**
     * Returns the key.
     *
     * @return the key
     */
    public Key getKey() {
        return key;
    }

    /**
     * Sets the key.
     *
     * @param key
     *            the key
     */
    public void setKey(Key key) {
        this.key = key;
    }

    /**
     * Returns the version.
     *
     * @return the version
     */
    public Long getVersion() {
        return version;
    }

    /**
     * Sets the version.
     *
     * @param version
     *            the version
     */
    public void setVersion(Long version) {
        this.version = version;
    }

    public String getServiceName() {
        return serviceName;
    }

    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }

    public String getConsumerToken() {
        return consumerToken;
    }

    public void setConsumerToken(String consumerToken) {
        this.consumerToken = consumerToken;
    }

    public String getServiceProvider() {
        return serviceProvider;
    }

    public void setServiceProvider(String serviceProvider) {
        this.serviceProvider = serviceProvider;
    }

    /**
     * サービスのコンシューマートークンを読み出して `OAuthConsumer` を生成します。
     * コンシューマートークンを読み出せない場合には例外を送出します。
     * 
     * TODO サービスレイヤーを作ってそちらに持って行く。
     * @param service
     * @return valid OAuth consumer instance
     * @throws RuntimeException in case of invalid settings 
     */
    public OAuthConsumer getConsumer()  {
        try {
            JSONObject token = new JSONObject(this.getConsumerToken());
            String consumerKey = token.getString("key");
            String consumerSecret = token.getString("secret");
            if (consumerKey == null || consumerSecret == null)
            {
                throw new JSONException("consumer key / secret is null.");
            }
            OAuthConsumer consumer = new DefaultOAuthConsumer(consumerKey, consumerSecret);
            return consumer;
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * サービスが持つプロバイダー情報を読み出して `OAuthProvider` を生成します。
     * プロバイダー情報を読み出せない場合には例外を送出します。
     * 
     * TODO サービスレイヤーを作ってそちらに持って行く。
     * @param service
     * @return valid OAuth provider instance
     * @throws RuntimeException in case of invalid settings 
     */
    public OAuthProvider getProvider()  {
        try {
            JSONObject serviceProvider = new JSONObject(this.getServiceProvider());
            // String method = token.getString("method");
            // String targetUrl = serviceProvider.getString("target");
            String requestUrl = serviceProvider.getString("request");
            String accessUrl = serviceProvider.getString("access");
            String authorizeUrl = serviceProvider.getString("authorize");
            if (requestUrl == null || accessUrl == null || authorizeUrl == null)
            {
                throw new JSONException("service provider has null value.");
            }
            OAuthProvider provider = new DefaultOAuthProvider(
                requestUrl, accessUrl, authorizeUrl);
            return provider;
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }
    }

    public String getTargetUrl(String type) {
        // 引数によって URL を可変にする？ 新着情報を取得する場合と、ユーザーの設定情報などを取得する場合。
        // 通知を解除しているグループ情報などを管理したくなるかもしれない。
        try {
            // キャッシュしておくか、別フィールドにするか、データ構造を変更した方が良いかも？
            JSONObject serviceProvider = new JSONObject(this.getServiceProvider());
            return serviceProvider.getString("target");
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((key == null) ? 0 : key.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        M_service other = (M_service) obj;
        if (key == null) {
            if (other.key != null) {
                return false;
            }
        } else if (!key.equals(other.key)) {
            return false;
        }
        return true;
    }
}